package com.xc.ezplan.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import com.xc.ezplan.admin.entity.AdminQiniuConfig;
import com.xc.ezplan.admin.entity.AdminQiniuContent;
import com.xc.ezplan.admin.mapper.AdminQiniuConfigMapper;
import com.xc.ezplan.admin.service.AdminQiniuContentService;
import com.xc.ezplan.admin.mapper.AdminQiniuContentMapper;
import com.xc.ezplan.admin.vo.AdminQiniuContentVo;
import com.xc.ezplan.core.base.BaseSearchBody;
import com.xc.ezplan.core.base.SearchCondition;
import com.xc.ezplan.core.exception.BadRequestException;
import com.xc.ezplan.core.properties.FileProperties;
import com.xc.ezplan.core.utils.FileUtil;
import com.xc.ezplan.core.utils.QiNiuUtil;
import com.xc.ezplan.core.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lixingchen
 * @date 2022/11/21
 * @description 七牛云内容实现类
 */
@Service
@Primary
@RequiredArgsConstructor
public class AdminQiniuContentServiceImpl extends ServiceImpl<AdminQiniuContentMapper, AdminQiniuContent>
		implements AdminQiniuContentService {

	private final AdminQiniuContentMapper adminQiniuContentMapper;

	private final AdminQiniuConfigMapper adminQiniuConfigMapper;

	private final FileProperties properties;

	@Override
	public void exportQiNiu(HttpServletResponse response, AdminQiniuContentVo adminQiniuContentVo) throws IOException {
		List<AdminQiniuContent> adminQiniuContents = adminQiniuContentMapper
				.selectList(new QueryWrapper<AdminQiniuContent>().lambda().eq(AdminQiniuContent::getName,
						adminQiniuContentVo.getName()));
		List<Map<String, Object>> list = new ArrayList<>();
		for (AdminQiniuContent content : adminQiniuContents) {
			Map<String, Object> map = new LinkedHashMap<>();
			map.put("文件名", content.getName());
			map.put("文件类型", content.getSuffix());
			map.put("空间名称", content.getBucket());
			map.put("文件大小", content.getSize());
			map.put("空间类型", content.getType());
			map.put("创建日期", content.getUpdateTime());
			list.add(map);
		}
		FileUtil.downloadExcel(list);
	}

	@Override
	public Object downloadQiNiu(Long id) {
		Map<String, Object> map = new HashMap<>(1);
		String finalUrl;
		String type = "公开";
		AdminQiniuContent adminQiniuContent = adminQiniuContentMapper.selectById(id);
		AdminQiniuConfig adminQiniuConfig = adminQiniuConfigMapper.selectById(adminQiniuContent.getConfigId());
		if (type.equals(adminQiniuContent.getType())) {
			finalUrl = adminQiniuContent.getUrl();
		} else {
			Auth auth = Auth.create(adminQiniuConfig.getAccessKey(), adminQiniuConfig.getSecretKey());
			// 1小时，可以自定义链接过期时间
			long expireInSeconds = 3600;
			finalUrl = auth.privateDownloadUrl(adminQiniuContent.getUrl(), expireInSeconds);
		}
		map.put("url", finalUrl);
		return map;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void deleteQiNiu(List<Long> ids,Long configId) {
		AdminQiniuConfig adminQiniuConfig = adminQiniuConfigMapper.selectById(configId);
		// 构造一个带指定Zone对象的配置类
		Configuration cfg = new Configuration(QiNiuUtil.getRegion(adminQiniuConfig.getZone()));
		Auth auth = Auth.create(adminQiniuConfig.getAccessKey(), adminQiniuConfig.getSecretKey());
		BucketManager bucketManager = new BucketManager(auth, cfg);
		for (Long id : ids) {
			AdminQiniuContent adminQiniuContent = adminQiniuContentMapper.selectById(id);
			try {
				bucketManager.delete(adminQiniuContent.getBucket(),
						adminQiniuContent.getName() + "." + adminQiniuContent.getSuffix());
			} catch (QiniuException e) {
				log.error("删除七牛云文件失败");
			}
			adminQiniuContentMapper.deleteById(id);
		}

	}

	@Override
	public void synchronizeQiNiu(Long configId) {
		AdminQiniuConfig adminQiniuConfig = adminQiniuConfigMapper.selectById(configId);
		if (adminQiniuConfig.getId() == null) {
			throw new BadRequestException("请先添加相应配置，再操作");
		}
		// 构造一个带指定Zone对象的配置类
		Configuration cfg = new Configuration(QiNiuUtil.getRegion(adminQiniuConfig.getZone()));
		Auth auth = Auth.create(adminQiniuConfig.getAccessKey(), adminQiniuConfig.getSecretKey());
		BucketManager bucketManager = new BucketManager(auth, cfg);
		// 文件名前缀
		String prefix = "";
		// 每次迭代的长度限制，最大1000，推荐值 1000
		int limit = 1000;
		// 指定目录分隔符，列出所有公共前缀（模拟列出目录效果）。缺省值为空字符串
		String delimiter = "";
		// 列举空间文件列表
		BucketManager.FileListIterator fileListIterator = bucketManager
				.createFileListIterator(adminQiniuConfig.getBucket(), prefix, limit, delimiter);
		while (fileListIterator.hasNext()) {
			// 处理获取的file list结果
			AdminQiniuContent qiniuContent;
			FileInfo[] items = fileListIterator.next();
			for (FileInfo item : items) {
				if (adminQiniuContentMapper.selectOne(new QueryWrapper<AdminQiniuContent>().lambda()
						.eq(AdminQiniuContent::getName, item.key)) == null) {
					qiniuContent = new AdminQiniuContent();
					qiniuContent.setSize(FileUtil.getSize(Integer.parseInt(item.fsize + "")));
					qiniuContent.setSuffix(FileUtil.getExtensionName(item.key));
					qiniuContent.setName(FileUtil.getFileNameNoEx(item.key));
					qiniuContent.setType(adminQiniuConfig.getType());
					qiniuContent.setBucket(adminQiniuConfig.getBucket());
					qiniuContent.setUrl(adminQiniuConfig.getHost() + "/" + item.key);
					qiniuContent.setConfigId(configId);
					adminQiniuContentMapper.insert(qiniuContent);
				}
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Object uploadQiNiu(MultipartFile file,Long configId) {
		AdminQiniuContent qiniuContent = upload(file, adminQiniuConfigMapper.selectById(configId));
		Map<String, Object> map = new HashMap<>(3);
		map.put("id", qiniuContent.getId());
		map.put("errno", 0);
		map.put("data", new String[] { qiniuContent.getUrl() });
		return map;
	}

	@Override
	public Object pageQueryQiNiu(BaseSearchBody<AdminQiniuContent> baseSearchBody) {
		Page<AdminQiniuContent> page = baseSearchBody.getPage();
		SearchCondition searchCondition = baseSearchBody.getSearchCondition();
		List<Date> createTime = searchCondition.getCreateTime();
		LambdaQueryWrapper<AdminQiniuContent> queryWrapper = new QueryWrapper<AdminQiniuContent>().lambda().like(
				StringUtils.isNotBlank(searchCondition.getKeyWord()), AdminQiniuContent::getName,
				searchCondition.getKeyWord()).eq(AdminQiniuContent::getConfigId,searchCondition.getQiNiuConfigId());
		if (!CollectionUtils.isEmpty(createTime) && createTime.size() == 2) {
			queryWrapper.between(AdminQiniuContent::getUpdateTime, createTime.get(0), createTime.get(1));
		}
		return adminQiniuContentMapper.selectPage(page, queryWrapper);
	}

	private AdminQiniuContent upload(MultipartFile file, AdminQiniuConfig qiniuConfig) {
		FileUtil.checkSize(properties.getMaxSize(), file.getSize());
		if (qiniuConfig.getId() == null) {
			throw new BadRequestException("请先添加相应配置，再操作");
		}
		// 构造一个带指定Zone对象的配置类
		Configuration cfg = new Configuration(QiNiuUtil.getRegion(qiniuConfig.getZone()));
		UploadManager uploadManager = new UploadManager(cfg);
		Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey());
		String upToken = auth.uploadToken(qiniuConfig.getBucket());
		try {
			String key = file.getOriginalFilename();
			if (adminQiniuContentMapper.selectOne(
					new QueryWrapper<AdminQiniuContent>().lambda().eq(AdminQiniuContent::getName, key)) != null) {
				key = QiNiuUtil.getKey(key);
			}
			Response response = uploadManager.put(file.getBytes(), key, upToken);
			// 解析上传成功的结果
			DefaultPutRet putRet = JSON.parseObject(response.bodyString(), DefaultPutRet.class);
			AdminQiniuContent content = adminQiniuContentMapper
					.selectOne(new QueryWrapper<AdminQiniuContent>().lambda().eq(AdminQiniuContent::getName, key));
			if (content == null) {
				// 存入数据库
				AdminQiniuContent qiniuContent = new AdminQiniuContent();
				qiniuContent.setSuffix(FileUtil.getExtensionName(putRet.key));
				qiniuContent.setBucket(qiniuConfig.getBucket());
				qiniuContent.setType(qiniuConfig.getType());
				qiniuContent.setName(FileUtil.getFileNameNoEx(putRet.key));
				qiniuContent.setUrl(qiniuConfig.getHost() + "/" + putRet.key);
				qiniuContent.setSize(FileUtil.getSize(Integer.parseInt(file.getSize() + "")));
				qiniuContent.setConfigId(qiniuConfig.getId());
				adminQiniuContentMapper.insert(qiniuContent);
				return adminQiniuContentMapper.selectById(qiniuContent.getId());
			}
			return content;
		} catch (Exception e) {
			throw new BadRequestException(e.getMessage());
		}
	}
}
